package core;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Random;
import java.util.Stack;
import java.util.Vector;

//import response.ResponseBoardEndTurn;
//import response.ResponseBoardPlayerTurn;

/**
 * @author Gary
 */
public class GameBoard extends GameMode {

    // Board Information
    private short type;
    private short width;
    private short height;
    private Short[] start;
    private Short[] end;
    //private GameBoardTile[][] pathTable;
    // Other Information
    //private GameBoardTile[][] boardTable;
    private HashMap<Integer, Stack<Short[]>> playerLocation;
    private Vector<Short> questionList;
    private int player_id;
    private short diceResult;
    private GameQuestion question;
    private short mode;
    private String topic_id;
    private short min_level;
    private short max_level;
    private int size;
    private int winner;
    private GameTimer questionTimer;
    private GameTimer diceTimer;

    public GameBoard(GameServer gameServer, short type, String map_id, short width, short height, int size, Short[] start, Short[] end, GameBoardTile[][] pathTable) {
        this.gameServer = gameServer;

        this.type = type;
        this.map_id = map_id;
        this.width = width;
        this.height = height;
        this.size = size;
        this.start = start;
        this.end = end;
        //this.pathTable = pathTable;
    }

    public GameBoard(int mode_id, String map_id, GameBoard gameBoard, short mode, String topic_id, short min_level, short max_level, Vector<GameCharacter> playerList) {
        mode_type = Constants.GAME_MODE_BOARD;

        this.mode_id = mode_id;
        this.map_id = map_id;

        //gameServer = gameBoard.getGameServer();

        //type = gameBoard.getType();
        //width = gameBoard.getWidth();
        //height = gameBoard.getHeight();
        //size = gameBoard.getSize();
        //start = gameBoard.getStart();
        //end = gameBoard.getEnd();
        //pathTable = gameBoard.getPathTable();

        this.mode = mode;
        this.topic_id = topic_id;
        this.min_level = min_level;
        this.max_level = max_level;

        //boardTable = new GameBoardTile[height][width];
        /*man-
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if (pathTable[i][j] != null) {
                    boardTable[i][j] = new GameBoardTile(pathTable[i][j]);

                    if (mode == Constants.BOARD_MODE_RACE) {
                        if (boardTable[i][j].getType() == Constants.BOARD_BLACKHOLE) {
                            boardTable[i][j].setType(Constants.BOARD_REGULAR);
                        }
                    }
                }
            }
        }

        Short[] nextLocation = Arrays.copyOf(start, start.length);

        for (int i = 0; i < size; i++) {
            GameBoardTile tile = boardTable[nextLocation[0]][nextLocation[1]];

            switch (tile.getDirection()) {
                case Constants.BOARD_NORTH:
                    nextLocation[0]--;
                    break;
                case Constants.BOARD_EAST:
                    nextLocation[1]++;
                    break;
                case Constants.BOARD_SOUTH:
                    nextLocation[0]++;
                    break;
                case Constants.BOARD_WEST:
                    nextLocation[1]--;
                    break;
            }

            if (i > 0 && i < size - 1) {
                tile.setReward(gameServer.getGameDB().getBugExperience(min_level + Math.round(i / (float) size / 2f * 10)));
            }
        }

        for (GameCharacter character : playerList) {
            playerLoadingList.put(character.getID(), character);
        }

        playerLocation = new HashMap<Integer, Stack<Short[]>>();

        for (GameCharacter character : playerList) {
            Stack<Short[]> locationList = new Stack<Short[]>();

            locationList.push(Arrays.copyOf(start, start.length));
            playerLocation.put(character.getID(), locationList);
        }*/

        questionList = new Vector<Short>();

        questionTimer = new GameTimer();
        diceTimer = new GameTimer();
    }

    public short getType() {
        return type;
    }

    public short getWidth() {
        return width;
    }

    public short getHeight() {
        return height;
    }

    public Short[] getStart() {
        return start;
    }

    public Short[] getEnd() {
        return end;
    }

    public short getMode() {
        return mode;
    }

    public short setMode(short mode) {
        return this.mode = mode;
    }

    public short getLevel() {
        return min_level;
    }

    public void setLevel(short min_level, short max_level) {
        this.min_level = min_level;
        this.max_level = max_level;
    }

    public int getSize() {
        return size;
    }
    /*man-
    @Override
    public GameCharacter removePlayer(int char_id) {
        GameCharacter character = getPlayer(char_id);

        if (character != null) {
            character.setGameMode(0);

            if (mode == Constants.BOARD_MODE_REGULAR) {
                playerList.remove(character);

                if (char_id == player_id) {
                    if (questionTimer.getTask() != null) {
                        questionTimer.getTask().cancel();
                    }

                    if (playerList.size() > 1) {
                        ResponseBoardEndTurn response = new ResponseBoardEndTurn();
                        response.set(gameServer);
                        response.setCharacter(character);

                        gameServer.updateCharacterUsersQueue(response, gameServer.getActiveModeUserList(mode_id));

                        ResponseBoardPlayerTurn playerResponse = new ResponseBoardPlayerTurn();
                        playerResponse.set(gameServer);
                        playerResponse.setCharacter(getNextPlayer());

                        gameServer.updateCharacterUsersQueue(playerResponse, gameServer.getActiveModeUserList(mode_id));
                    }
                }
            } else if (mode == Constants.BOARD_MODE_RACE) {
                playerList.remove(character);
            }

            if (playerList.size() < 2) {
                gameServer.getGameDB().setBoardGameWinner(mode_id, 0, 0);
                gameServer.removeGameMode(mode_id);
            }
        }

        return character;
    }*/

    public GameCharacter getCurrentPlayer() {
        return getPlayer(player_id);
    }
    /*man-
    public GameCharacter getNextPlayer() {
        GameCharacter character = playerList.get((playerList.indexOf(getCurrentPlayer()) + 1) % playerList.size());
        player_id = character.getID();

        return character;
    }

    public GameBoardTile[][] getPathTable() {
        return pathTable;
    }

    public short getDiceResult() {
        return diceResult;
    }

    public short useDice() {
        return diceResult = (short) (new Random().nextInt(6) + 1);
    }*/

    public GameTimer getQuestionTimer() {
        return questionTimer;
    }

    public void setQuestionTimer(int delay) {
        //questionTimer.schedule(new GameTimerCollection.GameBoardQuestionTimer(this), delay);
    }

    public void removeQuestionTimer() {
        if (questionTimer.getTask() != null) {
            questionTimer.getTask().cancel();
        }
    }

    public GameTimer getDiceTimer() {
        return diceTimer;
    }

    public void setDiceTimer(int delay) {
        //diceTimer.schedule(new GameTimerCollection.GameBoardDiceTimer(this), delay);
    }

    public void removeDiceTimer() {
        if (diceTimer.getTask() != null) {
            diceTimer.getTask().cancel();
        }
    }

    public void setStartTimer() {
        //startTimer.schedule(new GameTimerCollection.GameBoardStartTimer(this), startCountdown);
    }

    public void setEndTimer() {
        //endTimer.schedule(new GameTimerCollection.GameModeEndTimer(this), endCountdown);
    }

    public Vector<GameCharacter> randomizePlayers() {
        Collections.shuffle(playerList);
        player_id = playerList.get(0).getID();

        return playerList;
    }

    public Vector<Short[]> getPath(int char_id) {
        Vector<Short[]> pathList = new Vector<Short[]>();

        Short[] currentLocation = playerLocation.get(char_id).lastElement();
        pathList.add(Arrays.copyOf(currentLocation, currentLocation.length));

        Short[] nextLocation = Arrays.copyOf(currentLocation, currentLocation.length);

        GameBoardTile tile = null;

        for (int i = 0; i < diceResult; i++) {
            //tile = boardTable[nextLocation[0]][nextLocation[1]];

            switch (tile.getDirection()) {
                case Constants.BOARD_NORTH:
                    nextLocation[0]--;
                    break;
                case Constants.BOARD_EAST:
                    nextLocation[1]++;
                    break;
                case Constants.BOARD_SOUTH:
                    nextLocation[0]++;
                    break;
                case Constants.BOARD_WEST:
                    nextLocation[1]--;
                    break;
            }

            pathList.add(Arrays.copyOf(nextLocation, nextLocation.length));

            if (Arrays.equals(nextLocation, end)) {
                break;
            }
        }

        playerLocation.get(char_id).push(nextLocation);

        return pathList;
    }

    //public GameBoardTile getTile(Short[] location) {
        //return boardTable[location[0]][location[1]];
    //}

    //public GameBoardTile getTile(int row, int col) {
        //return boardTable[row][col];
    //}

    public GameQuestion getNewQuestion(GameServer gs) {
        question = gs.getGameDB().getQuestion(topic_id, questionList);

        if (question == null) {
            questionList.clear();
            question = gs.getGameDB().getQuestion(topic_id);
        }

        if (question != null) {
            questionList.add(question.getID());
        }

        return question;
    }

    public GameQuestion getQuestion() {
        return question;
    }

    public Short[] getPlayerLocation(int char_id) {
        return playerLocation.get(char_id).peek();
    }

    public Short[] setLastLocation(int char_id) {
        Stack<Short[]> locationList = playerLocation.get(char_id);

        if (locationList.size() > 1) {
            locationList.pop();
        }

        return locationList.peek();
    }

    public Short[] setStartLocation(int char_id) {
        Stack<Short[]> locationList = new Stack<Short[]>();

        locationList.push(Arrays.copyOf(start, start.length));
        playerLocation.put(char_id, locationList);

        return locationList.peek();
    }

    public int getWinner() {
        return winner;
    }

    public int setWinner(int char_id) {
        return this.winner = char_id;
    }

    @Override
    public void end() {
        super.end();

        if (questionTimer.getTask() != null) {
            questionTimer.getTask().cancel();
        }

        if (diceTimer.getTask() != null) {
            diceTimer.getTask().cancel();
        }
    }
}
